package com.enation.app.javashop.core.trade.cart.service.impl;

import com.enation.app.javashop.core.base.CachePrefix;
import com.enation.app.javashop.core.client.goods.GoodsClient;
import com.enation.app.javashop.core.goods.model.enums.GoodsType;
import com.enation.app.javashop.core.goods.model.vo.GoodsSkuVO;
import com.enation.app.javashop.core.trade.cart.model.enums.CartSourceType;
import com.enation.app.javashop.core.trade.cart.model.enums.CheckedWay;
import com.enation.app.javashop.core.trade.cart.service.CartPromotionManager;
import com.enation.app.javashop.core.trade.TradeErrorCode;
import com.enation.app.javashop.core.trade.cart.model.vo.CartSkuOriginVo;
import com.enation.app.javashop.core.trade.cart.service.CartOriginDataManager;
import com.enation.app.javashop.core.trade.cart.util.CartUtil;
import com.enation.app.javashop.framework.cache.Cache;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.security.model.Buyer;
import com.google.common.collect.Maps;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 购物车原始数据业务类实现<br>
 * 文档请参考：<br>
 * <a href="http://doc.javamall.com.cn/current/achitecture/jia-gou/ding-dan/cart-and-checkout.html" >购物车架构</a>
 *
 * @author kingapex
 * @version 1.0
 * @since 7.0.0
 * 2018/12/11
 */
@Service
public class CartOriginDataManagerImpl extends AbstractCartDataManagerImpl  implements CartOriginDataManager {

    protected final Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    private Cache cache;

    @Autowired
    private GoodsClient goodsClient;

    @Autowired
    private CartPromotionManager cartPromotionManager;


    /**
     * 由缓存中读取购物原始数据
     *
     * @return
     */
    @Override
    public List<CartSkuOriginVo> read(CheckedWay checkedWay) {
        return this.read(checkedWay,CartSourceType.COMMON_CART);
    }

    @Override
    public List<CartSkuOriginVo> read(CheckedWay checkedWay, CartSourceType cartSourceType) {
        List<CartSkuOriginVo> originList = (List<CartSkuOriginVo>) cache.get(CartUtil.getCartKey(checkedWay,cartSourceType));
        if(CollectionUtils.isEmpty(originList)){
            originList=new ArrayList<>();
        }
        return originList;
    }

    /**
     * 购物车添加商品
     * @param skuId          要写入的skuid
     * @param num            要加入购物车的数量
     * @param activityId     要参加的活动
     * @return
     */
    @Override
    public CartSkuOriginVo add(int skuId, int num, Integer activityId) {
        // 查询sku信息
        CartSkuOriginVo skuVo = null;
        GoodsSkuVO sku = this.goodsClient.getSkuFromCache(skuId);

        // 校验商品库存
        Integer enableQuantity = checkEnableQuantity(num, sku);

        // 判断购物车类型  社区团购 VS 商城
        CartSourceType cartSourceTypeEnum = getCartSourceTypeBySeller(sku.getSellerId());

        // 查询购物车所有商品
        List<CartSkuOriginVo> originList = this.read(CheckedWay.CART, cartSourceTypeEnum);

        // 更新或者新增购物车商品
        skuVo = updateSkuVo(skuId, num, cartSourceTypeEnum.name(), sku, enableQuantity, originList);

        // 新加入的商品都是选中的
        skuVo.setChecked(1);

        //填充可用的促销数据
        this.fillPromotion(skuVo, activityId);

        // 新人购限制选择 activityId=新人购活动 遍历所有sku 是否已经有新人购商品
        this.checkNewcomerLimitChoice(activityId,originList);

        //重新压入缓存（区分普通商品/社区团购商品）
        String key = CartUtil.getCartKey(CheckedWay.CART, cartSourceTypeEnum);
        cache.put(key, originList);

        // 购物车加购统计
        cartCount(num,UserContext.getBuyer().getUid(),sku);

        return skuVo;
    }

    private CartSkuOriginVo addBuyNow(int skuId, int num, Integer activityId,int memberId) {
        GoodsSkuVO sku = goodsClient.getSku(skuId);
        if (sku == null) {
            throw new ServiceException(TradeErrorCode.E451.code(), "商品已失效，请刷新购物车");
        }


        // 虚拟商品的限制条件
        if (GoodsType.VIRTUAL.name().equals(sku.getGoodsType()) && num != 1) {
            throw new ServiceException(TradeErrorCode.E490.code(), "虚拟商品只能购买一个");
        }

        //如果sku的可用库存小于等于0或者小于用户购买的数量，则不允许购买
        if (sku.getEnableQuantity().intValue() <= 0 || sku.getEnableQuantity().intValue() < num) {
            throw new ServiceException(TradeErrorCode.E451.code(), "商品库存已不足，不能购买。");
        }

        List<CartSkuOriginVo> originList = new ArrayList<>();
        CartSkuOriginVo skuVo = new CartSkuOriginVo();
        BeanUtils.copyProperties(sku, skuVo);

        //再设置加入购物车的数量
        skuVo.setNum(num);
        skuVo.setChecked(1);
        originList.add(skuVo);

        // 压入 （区分普通商品/社区团购商品/同城配送商品）
        CartSourceType cartSourceTypeEnum = getCartSourceTypeBySeller(sku.getSellerId());
        skuVo.setCartSourceType(cartSourceTypeEnum.name());

        //填充可用的促销数据
        this.fillPromotion(skuVo, activityId);

        String key = CartUtil.getCartKey(CheckedWay.BUY_NOW, cartSourceTypeEnum);
        cache.put(key, originList);

        //购物车商品加购统计消息
        cartCount(num, memberId, sku);

        return skuVo;
    }


    @Override
    public CartSkuOriginVo buy(Integer skuId, Integer num, Integer activityId,int memberId) {
        // 设置所有购物车商品unchecked
        checkedAll(0);
        // 重新添加购物车
        CartSkuOriginVo cartSkuOriginVo = addBuyNow(skuId, num, activityId,memberId);
        return cartSkuOriginVo;
    }


    @Override
    public CartSkuOriginVo updateNum(int skuId, int num,String cartSource) {

        Assert.notNull(skuId, "参数skuId不能为空");
        Assert.notNull(num, "参数num不能为空");

        GoodsSkuVO sku = this.goodsClient.getSkuFromCache(skuId);
        if (sku == null) {
            throw new ServiceException(TradeErrorCode.E451.code(), "商品已失效，请刷新购物车");
        }

        CartSourceType cartSourceType =CartSourceType.valueOf(cartSource);

        //读取sku的可用库存
        Integer enableQuantity = sku.getEnableQuantity();

        // 读取对应的购物车（社区团/普通商品）
        List<CartSkuOriginVo> originList = this.read(CheckedWay.CART, cartSourceType);

        //先看看购物车中是否存在此sku
        CartSkuOriginVo skuVo = this.findSku(skuId, originList);

        if (skuVo != null) {
            //话库存已经不足
            if (num > enableQuantity) {
                throw new ServiceException(TradeErrorCode.E451.code(), "此商品已经超出库存，库存为[" + enableQuantity + "]");
            }
            skuVo.setNum(num);

            // 限购数量
            cartPromotionManager.checkLimitNum(skuVo.getLimitNum(),skuVo.getNum(), skuVo.getSkuId());

            // 更新购物车缓存
            String key = CartUtil.getCartKey(CheckedWay.CART , cartSourceType);
            cache.put(key, originList);
        }

        return skuVo;
    }

    /**
     * 选中商品
     * @param skuId
     * @param checked
     * @param cartSourceType
     * @return
     */
    @Override
    public CartSkuOriginVo checked(int skuId, int checked,String cartSourceType) {
        //不合法的参数，忽略掉
        if (checked != 1 && checked != 0) {
            return new CartSkuOriginVo();
        }

        Assert.notNull(skuId, "参数skuId不能为空");

        CartSourceType cartSourceTypeEnum = CartSourceType.valueOf(cartSourceType);

        GoodsSkuVO sku = this.goodsClient.getSkuFromCache(skuId);

        List<CartSkuOriginVo> originList = this.read(CheckedWay.CART, cartSourceTypeEnum);

        CartSkuOriginVo cartSkuOriginVo = getCartSkuOriginVo(sku, checked, originList,cartSourceTypeEnum);

        return cartSkuOriginVo;
    }


    /**
     * 选中店铺
     * @param sellerId
     * @param checked
     * @param cartSourceType
     */
    @Override
    public void checkedSeller(int sellerId, int checked,String cartSourceType) {
        CartSourceType cartSourceTypeEnums = CartSourceType.valueOf(cartSourceType);
        //不合法的参数，忽略掉
        if (checked != 1 && checked != 0) {
            return;
        }

        Assert.notNull(sellerId, "参数sellerId不能为空");
        List<CartSkuOriginVo> originList = this.read(CheckedWay.CART, cartSourceTypeEnums);
        originList.forEach(cartSku -> {
            if (cartSku.getSellerId() == sellerId) {
                cartSku.setChecked(checked);
            }
        });

        String originKey = CartUtil.getCartKey(CheckedWay.CART,cartSourceTypeEnums);
        cache.put(originKey, originList);

    }


    /**
     * 选中所有商品
     * @param checked
     */
    @Override
    public void checkedAll(int checked) {
        //不合法的参数，忽略掉
        if (checked != 1 && checked != 0) {
            return;
        }

        //这是本次要返回的sku
        List<CartSkuOriginVo> originList = this.read(CheckedWay.CART, CartSourceType.COMMON_CART);
        originList.forEach(cartSku -> {
            cartSku.setChecked(checked);
        });

        cache.put(this.getOriginKey(CheckedWay.CART), originList);

        List<CartSkuOriginVo> shetuanList = this.read(CheckedWay.CART, CartSourceType.SHETUAN_CART);
        shetuanList.forEach(cartSku -> {
            cartSku.setChecked(checked);
        });

        cache.put(this.getShetuanKey(CheckedWay.CART), shetuanList);

    }


    /**
     * 批量删除购物车商品
     * @param skuIds
     * @param cartSourceType
     */
    @Override
    public void delete(Integer[] skuIds,String cartSourceType) {
        Assert.notNull(skuIds, "参数skuIds不能为空");

        //删除相关促销活动
        cartPromotionManager.delete(skuIds);
        //这是本次要返回的sku
        CartSourceType currentCarSourceType = CartSourceType.valueOf(cartSourceType);
        List<CartSkuOriginVo> oldList = this.read(CheckedWay.CART, currentCarSourceType);
        List<CartSkuOriginVo> newList = deleteCartSkus(skuIds, oldList);
        String cartKey = CartUtil.getCartKey(CheckedWay.CART, currentCarSourceType);
        // cache.remove(cartKey);
        logger.info("【删除购物车】"+newList.toString());
        cache.put(cartKey, newList);
    }


    @Override
    public void clean() {
        //清空此用户所有选择的促销活动
        cartPromotionManager.clean();
        cache.remove(this.getOriginKey(CheckedWay.CART));
        cache.remove(this.getShetuanKey(CheckedWay.CART));
    }

    @Override
    public void cleanChecked() {
        String originKey = this.getOriginKey(CheckedWay.CART);

        //这是本次要返回的sku
        List<CartSkuOriginVo> originList = this.read(CheckedWay.CART);
        List<CartSkuOriginVo> newList = new ArrayList<>();
        List<Integer> skuIds = new ArrayList<>();

        originList.forEach(cartSku -> {

            //如果是选中的则要删除（也就是未选中的才压入list）
            if (cartSku.getChecked() == 0) {
                newList.add(cartSku);
            } else {
                skuIds.add(cartSku.getSkuId());
            }

        });

        //清除相关sku的优惠活动
        cartPromotionManager.delete(skuIds.toArray(new Integer[skuIds.size()]));

        //清除用户选择的所有的优惠券
        cartPromotionManager.cleanCoupon();
        cache.put(originKey, newList);

    }


    @Override
    public   Map<Integer, Integer> getUserCart() {
        Buyer buyer = UserContext.getBuyer();
        Map<Integer, Integer> cartNumMap = Maps.newHashMap();
        if (buyer != null) {
            List<CartSkuOriginVo> cartSkuList =
                    (List<CartSkuOriginVo>) cache.get(CachePrefix.CART_SHETUAN_DATA_PREFIX.getPrefix() + buyer.getUid());
            if (!CollectionUtils.isEmpty(cartSkuList)) {
                cartNumMap = cartSkuList.stream().collect(Collectors.toMap(CartSkuOriginVo::getSkuId, CartSkuOriginVo::getNum));
            }
        }
        return cartNumMap;
    }

}
